/*******************************************************************************
* Copyright (c) 2004, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.ui.internal.dnd;
//import java.util.ArrayList;
//import java.util.Iterator;
//import java.util.List;
import org.eclipse.jface.util.Geometry;
//import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Control;
//import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
//import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
//import org.eclipse.swt.widgets.Tracker;
//import org.eclipse.ui.PlatformUI;
//import org.eclipse.ui.internal.DragCursors;
/**
* Provides the methods for attaching drag-and-drop listeners to SWT controls.
*/
public class DragUtil {
// RAP [rh] DnD not implemented
// private static final String DROP_TARGET_ID = "org.eclipse.ui.internal.dnd.dropTarget"; //$NON-NLS-1$
// RAP [rh] DnD not implemented
// /**
// * The location where all drags will end. If this is non-null, then
// * all user input is ignored in drag/drop. If null, we use user input
// * to determine where objects should be dropped.
// */
// private static TestDropLocation forcedDropTarget = null;
// RAP [rh] DnD not implemented
// /**
// * List of IDragOverListener
// */
// private static List defaultTargets = new ArrayList();
// RAP [rh] DnD not implemented
// /**
// * Sets the drop target for the given control. It is possible to add one or more
// * targets for a "null" control. This becomes a default target that is used if no
// * other targets are found (for example, when dragging objects off the application
// * window).
// *
// * @param control the control that should be treated as a drag target, or null
// * to indicate the default target
// * @param target the drag target to handle the given control
// */
// public static void addDragTarget(Control control, IDragOverListener target) {
// if (control == null) {
// defaultTargets.add(target);
// } else {
// List targetList = getTargetList(control);
//
// if (targetList == null) {
// targetList = new ArrayList(1);
// }
// targetList.add(target);
// control.setData(DROP_TARGET_ID, targetList);
// }
// }
// RAP [rh] DnD not implemented
// /**
// * Return the list of 'IDragOverListener' elements associated with
// * the given control. If there's a 'global' listener then always
// * return it.
// *
// * @param control
// * @return
// */
// private static List getTargetList(Control control) {
// List result = (List) control.getData(DROP_TARGET_ID);
// return result;
// }
// RAP [rh] DnD not implemented
// /**
// * Removes a drop target from the given control.
// *
// * @param control
// * @param target
// */
// public static void removeDragTarget(Control control,
// IDragOverListener target) {
// if (control == null) {
// defaultTargets.remove(target);
// } else {
// List targetList = getTargetList(control);
// if (targetList != null) {
// targetList.remove(target);
// if (targetList.isEmpty()) {
// control.setData(DROP_TARGET_ID, null);
// }
// }
// }
// }
/**
* Shorthand method. Returns the bounding rectangle for the given control, in
* display coordinates. Note that all 'Shell' controls are expected to be 'top level'
* so DO NOT do the origin offset for them.
*
* @param draggedItem
* @param boundsControl
* @return
*/
public static Rectangle getDisplayBounds(Control boundsControl) {
Control parent = boundsControl.getParent();
if (parent == null || boundsControl instanceof Shell) {
return boundsControl.getBounds();
}
return Geometry.toDisplay(parent, boundsControl.getBounds());
}
// RAP [rh] DnD not implemented
// public static boolean performDrag(final Object draggedItem,
// Rectangle sourceBounds, Point initialLocation, boolean allowSnapping) {
//
// IDropTarget target = dragToTarget(draggedItem, sourceBounds,
// initialLocation, allowSnapping);
//
// if (target == null) {
// return false;
// }
//
// target.drop();
//
// // If the target can handle a 'finished' notification then send one
// if (target!= null && target instanceof IDropTarget2) {
// ((IDropTarget2)target).dragFinished(true);
// }
//
// return true;
// }
// RAP [rh] DnD not implemented
// /**
// * Drags the given item to the given location (in display coordinates). This
// * method is intended for use by test suites.
// *
// * @param draggedItem object being dragged
// * @param finalLocation location being dragged to
// * @return true iff the drop was accepted
// */
// public static boolean dragTo(Display display, Object draggedItem,
// Point finalLocation, Rectangle dragRectangle) {
// Control currentControl = SwtUtil.findControl(display, finalLocation);
//
// IDropTarget target = getDropTarget(currentControl, draggedItem,
// finalLocation, dragRectangle);
//
// if (target == null) {
// return false;
// }
//
// target.drop();
//
// return true;
// }
// RAP [rh] DnD not implemented
// /**
// * Forces all drags to end at the given position (display coordinates). Intended
// * for use by test suites. If this method is called, then all subsequent calls
// * to performDrag will terminate immediately and behave as though the object were
// * dragged to the given location. Calling this method with null cancels this
// * behavior and causes performDrag to behave normally.
// *
// * @param forcedLocation location where objects will be dropped (or null to
// * cause drag/drop to behave normally).
// */
// public static void forceDropLocation(TestDropLocation forcedLocation) {
// forcedDropTarget = forcedLocation;
// }
// RAP [rh] DnD not implemented
// /**
// * Drags the given item, given an initial bounding rectangle in display coordinates.
// * Due to a quirk in the Tracker class, changing the tracking rectangle when using the
// * keyboard will also cause the mouse cursor to move. Since "snapping" causes the tracking
// * rectangle to change based on the position of the mouse cursor, it is impossible to do
// * drag-and-drop with the keyboard when snapping is enabled.
// *
// * @param draggedItem object being dragged
// * @param sourceBounds initial bounding rectangle for the dragged item
// * @param initialLocation initial position of the mouse cursor
// * @param allowSnapping true iff the rectangle should snap to the drop location. This must
// * be false if the user might be doing drag-and-drop using the keyboard.
// *
// * @return
// */
// static IDropTarget dragToTarget(final Object draggedItem,
// final Rectangle sourceBounds, final Point initialLocation,
// final boolean allowSnapping) {
// final Display display = Display.getCurrent();
//
// // Testing...immediately 'drop' onto the test target
// if (forcedDropTarget != null) {
// Point location = forcedDropTarget.getLocation();
//
// Control currentControl = SwtUtil.findControl(forcedDropTarget.getShells(), location);
// return getDropTarget(currentControl, draggedItem, location,
// sourceBounds);
// }
//
// // Create a tracker. This is just an XOR rect on the screen.
// // As it moves we notify the drag listeners.
// final Tracker tracker = new Tracker(display, SWT.NULL);
// tracker.setStippled(true);
//
// tracker.addListener(SWT.Move, new Listener() {
// public void handleEvent(final Event event) {
// display.syncExec(new Runnable() {
// public void run() {
// // Get the curslor location as a point
// Point location = new Point(event.x, event.y);
//
// // Select a drop target; use the global one by default
// IDropTarget target = null;
//
// Control targetControl = display.getCursorControl();
//
// // Get the drop target for this location
// target = getDropTarget(targetControl,
// draggedItem, location,
// tracker.getRectangles()[0]);
//
// // Set up the tracker feedback based on the target
// Rectangle snapTarget = null;
// if (target != null) {
// snapTarget = target.getSnapRectangle();
//
// tracker.setCursor(target.getCursor());
// } else {
// tracker.setCursor(DragCursors
// .getCursor(DragCursors.INVALID));
// }
//
// // If snapping then reset the tracker's rectangle based on the current drop target
// if (allowSnapping) {
// if (snapTarget == null) {
// snapTarget = new Rectangle(sourceBounds.x
// + location.x - initialLocation.x,
// sourceBounds.y + location.y
// - initialLocation.y,
// sourceBounds.width, sourceBounds.height);
// }
//
// // Try to prevent flicker: don't change the rectangles if they're already in
// // the right location
// Rectangle[] currentRectangles = tracker.getRectangles();
//
// if (!(currentRectangles.length == 1 && currentRectangles[0]
// .equals(snapTarget))) {
// tracker.setRectangles(new Rectangle[] { snapTarget });
// }
// }
// }
// });
// }
// });
//
// // Setup...when the drag starts we might already be over a valid target, check this...
// // If there is a 'global' target then skip the check
// IDropTarget target = null;
// Control startControl = display.getCursorControl();
//
// if (startControl != null && allowSnapping) {
// target = getDropTarget(startControl,
// draggedItem, initialLocation,
// sourceBounds);
// }
//
// // Set up an initial tracker rectangle
// Rectangle startRect = sourceBounds;
// if (target != null) {
// Rectangle rect = target.getSnapRectangle();
//
// if (rect != null) {
// startRect = rect;
// }
//
// tracker.setCursor(target.getCursor());
// }
//
// if (startRect != null) {
// tracker.setRectangles(new Rectangle[] { Geometry.copy(startRect)});
// }
//
// // Tracking Loop...tracking is preformed on the 'SWT.Move' listener registered
// // against the tracker.
//
// // HACK:
// // Some control needs to capture the mouse during the drag or other
// // controls will interfere with the cursor
// Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
// if (shell != null) {
// shell.setCapture(true);
// }
//
// // Run tracker until mouse up occurs or escape key pressed.
// boolean trackingOk = tracker.open();
//
// // HACK:
// // Release the mouse now
// if (shell != null) {
// shell.setCapture(false);
// }
//
// // Done tracking...
//
// // Get the current drop target
// IDropTarget dropTarget = null;
// Point finalLocation = display.getCursorLocation();
// Control targetControl = display.getCursorControl();
// dropTarget = getDropTarget(targetControl, draggedItem,
// finalLocation, tracker.getRectangles()[0]);
//
// // Cleanup...
// tracker.dispose();
//
// // if we're going to perform a 'drop' then delay the issuing of the 'finished'
// // callback until after it's done...
// if (trackingOk) {
// return dropTarget;
// }
// else if (dropTarget!= null && dropTarget instanceof IDropTarget2) {
// // If the target can handle a 'finished' notification then send one
// ((IDropTarget2)dropTarget).dragFinished(false);
// }
//
// return null;
// }
// RAP [rh] DnD not implemented
// /**
// * Given a list of IDragOverListeners and a description of what is being dragged, it returns
// * a IDropTarget for the current drop.
// *
// * @param toSearch
// * @param mostSpecificControl
// * @param draggedObject
// * @param position
// * @param dragRectangle
// * @return
// */
// private static IDropTarget getDropTarget(List toSearch,
// Control mostSpecificControl, Object draggedObject, Point position,
// Rectangle dragRectangle) {
// if (toSearch == null) {
// return null;
// }
//
// Iterator iter = toSearch.iterator();
// while (iter.hasNext()) {
// IDragOverListener next = (IDragOverListener) iter.next();
//
// IDropTarget dropTarget = next.drag(mostSpecificControl,
// draggedObject, position, dragRectangle);
//
// if (dropTarget != null) {
// return dropTarget;
// }
// }
//
// return null;
// }
// RAP [rh] DnD not implemented
// /**
// * Returns the drag target for the given control or null if none.
// *
// * @param toSearch
// * @param e
// * @return
// */
// public static IDropTarget getDropTarget(Control toSearch,
// Object draggedObject, Point position, Rectangle dragRectangle) {
// // Search for a listener by walking the control's parent hierarchy
// for (Control current = toSearch; current != null; current = current
// .getParent()) {
// IDropTarget dropTarget = getDropTarget(getTargetList(current),
// toSearch, draggedObject, position, dragRectangle);
//
// if (dropTarget != null) {
// return dropTarget;
// }
//
// // Don't look to parent shells for drop targets
// if (current instanceof Shell) {
// break;
// }
// }
//
// // No controls could handle this event -- check for default targets
// return getDropTarget(defaultTargets, toSearch, draggedObject, position,
// dragRectangle);
// }
/**
* Returns the location of the given event, in display coordinates
* @return
*/
public static Point getEventLoc(Event event) {
Control ctrl = (Control) event.widget;
return ctrl.toDisplay(new Point(event.x, event.y));
}
}